from template import Handle, fillAttr, quoteAndFillAttr, funcTable
from IOBuffer import IOBuffer
from xhtmltools import urlencode
from templatehelper import quoteattr, escape, evalKey, toUni
def fillTemplate(data, domHandler):
# Start of handle
handle = Handle(domHandler)
out = IOBuffer()
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n")
out.write(u'></meta>\n<script type="text/javascript">\n<!-- // Protect from our XML parser, which doesn\'t know to protect <script>\n\n///////////////////////////////////////////////////////////////////////////////\n//// Machinery related to dynamic updates in full XUL mode ////\n///////////////////////////////////////////////////////////////////////////////\n\nfunction handleUpdate(event) {\n r = event.target;\n eval(r.responseText);\n}\n\nfunction beginUpdates() {\n if (getDTVPlatform() == \'xul\') {\n // Under XUL, open a \'push\' HTTP connection to the controller to\n // receive updates. This avoids calling across the Python/XPCOM\n // boundary, which causes deadlocks sometimes for poorly understood\n // reasons.\n // port = getServerPort();\n var cookie = getEventCookie();\n // url = "http://127.0.0.1:" + port + "/dtv/mutators/" + cookie;\n var url = "/dtv/mutators/" + cookie;\n\n var xr = new XMLHttpRequest();\n /*\n netscape.security.PrivilegeManager.\n enablePrivilege("UniversalBrowserRead");\n */\n xr.multipart = true;\n xr.open("GET", url, true);\n xr.onload = handleUpdate;\n xr.send(null);\n }\n}\n \n///////////////////////////////////////////////////////////////////////////////\n//// For use on your page ////\n///////////////////////////////////////////////////////////////////////////////\n\nfunction jsdump(str) {\n Components.classes[\'@mozilla.org/consoleservice;1\']\n\t.getService(Components.interfaces.nsIConsoleService)\t\n\t.logStringMessage(str);\n}\n\nfunction getEventCookie() {\n var elt = document.getElementsByTagName("html")[0];\n return elt.getAttribute(\'eventCookie\');\n}\n\nfunction getDTVPlatform() {\n var elt = document.getElementsByTagName("html")[0];\n return elt.getAttribute(\'dtvPlatform\');\n}\n\n/*\n// NEEDS: eliminate! just use relative URLs\nfunction getServerPort() {\n var elt = document.getElementsByTagName("html")[0];\n return elt.getAttribute(\'serverPort\');\n}\n*/\n\n// For calling from page Javascript: Cause a URL to be loaded. The\n// assumption is that the application will notice, abort the load, and\n// take some action based on the URL.\nfunction eventURL(url) {\n if (getDTVPlatform() == \'xul\') {\n \t// XUL strategy: async HTTP request to our in-process HTTP\n // server. Since it falls under the "same origin" security\n // model exemption, no need for complicated preferences\n // shenanigans -- what a nice day!\n // url = "http://127.0.0.1:" + getServerPort() + "/dtv/action/" +\n // getEventCookie() + "?" + url; NEEDS: remove\n url = "/dtv/action/" + getEventCookie() + "?" + url;\n \tvar req = new XMLHttpRequest();\n req.open("GET", url, true);\n req.send(null);\n // NEEDS: there is another copy of this in main.js.\n }\n else if (typeof(window.frontend) == \'undefined\') {\n\t// Generic strategy: trigger a load, and hope the application\n\t// catches it and cancels it without creating a race\n\t// condition.\n\tdocument.location.href = url;\n } else {\n\t// OS X WebKit (KHTML) strategy: pass in an Objective C object\n\t// through the window object and call a method on it.\n\twindow.frontend.eventURL(url);\n }\n\n return false;\n} \n\n// Open email client with email about selected video\n// All parameters come in URL encoded\nfunction recommendItem(title, url, feedURL) {\n url = URLdecode(url);\n feedURL = URLdecode(feedURL);\n body = "You should check out this video:\\n";\n body = body + url + "\\n\\n";\n body = body + "I found it while using the Democracy Player, which you can download here:\\n";\n body = body + "http://www.getdemocracy.com\\n\\n";\n body = body + "The video was on this channel (click \'subscribe\' in Democracy and paste in this address):\\n"\n body = body + feedURL + "\\n\\n"\n \n url = \'mailto:\';\n url = url + "?subject=" + title;\n url = url + "&body=" + URLencode(body);\n eventURL(url);\n \n return false;\n}\n\n// Change a view\'s filter. The filter controls which records are\n// included and which are not. (You can only do this if, when the view\n// was declared in the page header, it was given an initial filter\n// with the t:filter tag.) viewName is the name of the view whose\n// filter should be changed, as declared in the t:view tag. fieldKey\n// is the property of the record that should be tested (eg, \'name\'.)\n// functionKey is the function that should be used to do the test (eg,\n// \'global filter substring\'.) parameter is an extra parameter to pass\n// to the test function (such as a search string). If invert is true,\n// the sense of the filter is reversed: only objects that don\'t match\n// it will be included. For convenience in \'onclick\' handlers, this\n// function returns false. param is a hack to include a static\n// parameter in addition to the dynamic one.\nfunction setViewFilter(viewName, fieldKey, functionKey, parameter, invert, param) {\n url = \'action:setViewFilter?\';\n url = url + \'viewName=\' + URLencode(viewName);\n url = url + \'&fieldKey=\' + URLencode(fieldKey);\n url = url + \'&functionKey=\' + URLencode(functionKey);\n if (parameter)\n\turl = url + \'¶meter=\' + URLencode(param+\'|\'+parameter);\n else\n\turl = url + \'¶meter=\'+ URLencode(param);\n if (invert)\n\turl = url + \'&invert=true\';\n else\n\turl = url + \'&invert=false\';\n eventURL(url);\n return false;\n}\n\n// Change a view\'s sort. The sort controls the order in which records\n// are displayed. (You can only do this if, when the view was declared\n// in the page header, it was given an initial sort with the t:sort\n// tag.) viewName is the name of the view whose sort should be\n// changed, as declared in the t:view tag. fieldKey is the property of\n// the record to sort on (eg, \'name\'.) functionKey is the comparison\n// function for the sort (eg, \'global sort text\'.) If reverse is true,\n// the records will be shown in the opposite of their normal order as\n// defined by the other parameters. For convenience in \'onclick\'\n// handlers, this function returns false.\nfunction setViewSort(viewName, fieldKey, functionKey, reverse) {\n url = \'action:setViewSort?\';\n url = url + \'viewName=\' + URLencode(viewName);\n url = url + \'&fieldKey=\' + URLencode(fieldKey);\n url = url + \'&functionKey=\' + URLencode(functionKey);\n if (reverse)\n\turl = url + \'&reverse=true\';\n eventURL(url);\n return false;\n}\n\n// Start the video player. The playlist will be the items in the view\n// named by viewName. If firstItemId is the id of an item in the view,\n// playback will start on that item; otherwise playback will start on\n// the first item.\nfunction playViewNamed(viewName, firstItemId) {\n url = \'action:playViewNamed?\';\n url = url + \'viewName=\' + URLencode(viewName);\n url = url + \'&firstItemId=\' + URLencode(firstItemId);\n eventURL(url);\n return false;\n}\n\n// You can make \'incremental search\' text boxes on your page that\n// effectively tie the text box to the \'parameter\' argument of setViewFilter,\n// with the other argumens fixed. To do this, add these two attributes to\n// the text box:\n// onfocus="startEditFilter(this, (viewName), (fieldKey),\n// (functionKey), (invert), (param)"\n// onblur="endEditFilter()"\n// replacing the arguments in parentheses with the desired strings.\n//\n// Note that params is a big hack to pass a static parameter in\n// addition to the dynamic one\n\nvar editFilterTimers = new Array();\nvar editFilterField = null;\nvar editFilterOldValue = \'\';\nvar editFilterCount = 0;\nvar editFilterViews = new Array();\nvar editFilterFieldKeys = new Array();\nvar editFilterFunctionKeys = new Array();\nvar editFilterInverts = new Array();\nvar editFilterParams = new Array();\nvar editCurView = 0;\n\nfunction startEditFilter(obj, views, fieldKeys, functionKeys, inverts, params) {\n editFilterOldValue = obj.value;\n\n editFilterField = obj;\n editFilterViews = views;\n editFilterFieldKeys = fieldKeys;\n editFilterFunctionKeys = functionKeys;\n editFilterInverts = inverts;\n editFilterParams = params;\n editCurView = 0;\n\n editFilterTimerTick(editCurView);\n}\n\nfunction editFilterUpdate(viewName,functionName,fieldName,invert, param) {\n value = editFilterField.value;\n if (editFilterOldValue != value ||\n\teditFilterCount < editFilterViews.length) {\n\tif (editFilterOldValue != value) \n\t editFilterCount = 0;\n\telse\n\t editFilterCount++;\n\tsetViewFilter(viewName, fieldName,\n\t\t functionName, value,\n\t\t invert, param);\n\teditFilterOldValue = value;\n }\n}\n\nfunction editFilterTimerTick(curView) {\n editFilterUpdate(editFilterViews[editCurView],editFilterFunctionKeys[editCurView],editFilterFieldKeys[editCurView],editFilterInverts[editCurView], editFilterParams[editCurView]);\n editCurView++;\n if (editCurView >= editFilterViews.length) {\n\teditCurView = 0;\n }\n editFilterTimer = setTimeout(editFilterTimerTick, 50);\n}\n\nfunction endEditFilter() {\n clearTimeout(editFilterTimer);\n editFilterCount = 0;\n editFilterUpdate();\n}\n\n// Internal use: \'URL encode\' the given string.\nfunction URLencode(str) {\n return encodeURIComponent(str)\n}\n\nfunction URLdecode(str) {\n return decodeURIComponent(str)\n}\n\n///////////////////////////////////////////////////////////////////////////////\n//// For calling by host templating code ////\n///////////////////////////////////////////////////////////////////////////////\n\n// For calling by host templating code: Returns items that should\n// appear in the context click menu in the format url|description with\n// one item on each line. Blank lines are separators\nfunction getContextClickMenu(element) {\n while (1) {\n\tif (element.nodeType == 1 && element.getAttribute(\'t:contextMenu\')) {\n\t ret = element.getAttribute(\'t:contextMenu\');\n\t ret = ret.replace(/\\\\n/g,"\\n");\n\t ret = ret.replace(/\\\\\\\\/g,"\\\\");\n\t return ret;\n\t}\n\tif (element.parentNode)\n\t element = element.parentNode;\n\telse\n\t return "";\n }\n\n // Satisfy Mozilla that the function always returns a\n // value. Otherwise, we get an error if strict mode is enabled,\n // ultimately preventing us from getting the state change event\n // indicating that the load succeeded.\n return "";\n}\n\n// For calling by host templating code: Set CSS styles on the item\n// with the given ID to make it disappear.\nfunction hideItem(id) {\n elt = document.getElementById(id);\n elt.style.display = \'none\';\n forceRedisplay(elt);\n}\n\n// For calling by host templating code: Set CSS styles on the item\n// with the given ID to make it visible if it was previously hidden.\nfunction showItem(id) {\n elt = document.getElementById(id);\n elt.style.display = \'\';\n forceRedisplay(elt);\n}\n\n// For calling by host templating code: Replace the item with the\n// given id with the element described by the proided XML.\nfunction changeItem(id, newXML) {\n elt = document.getElementById(id);\n r = document.createRange();\n r.selectNode(elt);\n frag = r.createContextualFragment(newXML);\n elt.parentNode.replaceChild(frag, elt);\n}\n\n// For calling by host templating code: Parse the XML in newXML into a\n// new element, and insert the new element immediately before the item\n// with the given id, such that the newly inserted item has the same\n// parent.\nfunction addItemBefore(newXML, id) {\n elt = document.getElementById(id);\n r = document.createRange();\n r.selectNode(elt);\n frag = r.createContextualFragment(newXML);\n elt.parentNode.insertBefore(frag, elt);\n} \n\n// For calling by host templating code: Parse the XML in newXML into a\n// new element, and insert the new element as the final child of the\n// item with the given id.\nfunction addItemAtEnd(newXML, id) {\n elt = document.getElementById(id);\n r = document.createRange();\n r.selectNode(elt);\n frag = r.createContextualFragment(newXML);\n elt.insertBefore(frag, null);\n} \n\n// For calling by host templating code: Remove the item with the given\n// id.\nfunction removeItem(id) {\n elt = document.getElementById(id);\n elt.parentNode.removeChild(elt);\n} \n\n// Internal use: Sometime if all you do is change the style on a node,\n// Safari doesn\'t update the view until your mouse is next over the\n// window. Force the issue by making a drastic change in the vicinity\n// of the given element and then reversing it.\nfunction forceRedisplay(elt) {\n r = document.createRange();\n r.selectNode(elt);\n frag = r.extractContents();\n r.insertNode(frag);\n}\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\n-->\n</script>\n\n</head>\n<body>\n\nA doubly nested template. My favorite color is <span>')